package com.casic.modules.activiti.service;

import com.casic.modules.activiti.entity.HistoricActivity;
import com.casic.modules.activiti.entity.ProcessDefinition;
import com.casic.modules.activiti.util.JqGridPageView;
import com.casic.modules.activiti.util.StringUtils;
import com.casic.modules.activiti.util.WorkFlowUtils;
import com.casic.modules.sys.entity.SysUserEntity;
import com.casic.modules.sys.service.SysUserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.form.StartFormDataImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Comment;
import org.activiti.image.ProcessDiagramGenerator;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.Map.Entry;
import java.util.zip.ZipInputStream;

/**
 * @author htkjsx
 * @version 2016年5月20日 下午3:16:07
 */
@Service
public class ActFlowService  {
	@Autowired
	private ProcessEngine processEngine;

	@Autowired
	private FormService formService;

	@Autowired
	private RepositoryService repositoryService;

	@Autowired
	private IdentityService identityService;

	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private ProcessEngineConfiguration processEngineConfiguration;
	@Autowired
	private TaskService taskService;
	@Autowired
	private SysUserService sysUserService;

	protected ObjectMapper objectMapper = new ObjectMapper();
	/**
	 *
	 * @Title deoploymentForClasspath
	 * @Description (按照bpmn和png文件定义部署流程)
	 * @author 颜金星
	 * @create 2017年5月11日-上午11:41:16
	 * @Param @param params
	 * @return void
	 * @throws
	 */
	public Deployment deoploymentForClasspath(Map<String, Object> params){
		//"act/designs/oa/test_audit/test_audit.bpmn"
		//"act/designs/oa/test_audit/test_audit.png"
		Deployment deployment = processEngine.getRepositoryService() // 与流程定义和部署对象相关的service  
				.createDeployment()// 创建一个部署对象
				.name((String)params.get("flowName"))// 添加部署的名称
				.addClasspathResource((String)params.get("bpmn"))// 从classpath的资源中加载，一次只能加载一个文件
				.addClasspathResource((String)params.get("png"))// 从classpath的资源中加载，一次只能加载一个文件
				.deploy();// 完成部署
		System.out.println("部署ID：" + deployment.getId());
		System.out.println("部署名称:" + deployment.getName());
		return deployment;
	}
	/**
	 *
	 * @Title deoploymentForZip
	 * @Description (按照zip文件定义部署流程)
	 * @author 颜金星
	 * @create 2017年5月11日-上午11:42:03
	 * @Param @param params
	 * @return void
	 * @throws
	 */
	public Deployment deoploymentForZip(Map<String, Object> params){
		//act/designs/oa/test_audit/test_audit.zip
		InputStream in = this.getClass().getClassLoader()
				.getResourceAsStream((String)params.get("zip"));
		ZipInputStream zipInputStream = new ZipInputStream(in);
		Deployment deployment = processEngine.getRepositoryService()// 与流程定义和部署对象相关的service
				.createDeployment()// 创建一个部署对象
				.name((String)params.get("flowName"))// 添加部署
				.addZipInputStream(zipInputStream)// 指定zip格式的文件完成部署
				.deploy();// 完成部署
		System.out.println("部署ID：" + deployment.getId());
		System.out.println("部署名称:" + deployment.getName());
		return deployment;
	}
	/**
	 *
	 * @Title findProcessDefinition
	 * @Description (条件查询以定义部署,带版本重复数据)
	 * @author 颜金星
	 * @create 2017年5月11日-上午11:42:27
	 * @Param
	 * @return void
	 * @throws
	 */
	public PageInfo<ProcessDefinition> findProcessByPage(Map<String, Object> params) {
		PageInfo<ProcessDefinition> page=new PageInfo<ProcessDefinition>();
		ProcessDefinitionQuery  processDefinitionQuery= processEngine.getRepositoryService().createProcessDefinitionQuery();
		String flowName=(String)params.get("flowName");
		if(flowName!=null&&!"".equals(flowName)){
			processDefinitionQuery.processDefinitionName(flowName);
		}
		processDefinitionQuery.orderByProcessDefinitionVersion().desc();
		List<org.activiti.engine.repository.ProcessDefinition> list=processDefinitionQuery.listPage(Integer.parseInt((String)params.get("pageNum")), Integer.parseInt((String)params.get("pageSize")));
		long count=processDefinitionQuery.count();
		page.setTotal(count);
		List<ProcessDefinition> dataList=new ArrayList<ProcessDefinition>();
		ProcessDefinition processDefinition=null;
		for(org.activiti.engine.repository.ProcessDefinition pd : list){
			processDefinition=new ProcessDefinition();
			processDefinition.setId(pd.getId());
			processDefinition.setName(pd.getName());
			processDefinition.setKey(pd.getKey());
			processDefinition.setVersion(pd.getVersion()+"");
			processDefinition.setResourceName(pd.getResourceName());
			processDefinition.setDiagramResourceName(pd.getDiagramResourceName());
			processDefinition.setDeploymentId(pd.getDeploymentId());
			dataList.add(processDefinition);
		}
		page.setList(dataList);
		return page;
	}
	/**
	 *
	 * @Title findFlowByPage
	 * @Description (分页查询流程定义)
	 * @author 颜金星
	 * @create 2017年5月24日-上午10:03:18
	 * @Param @param params
	 * @Param @return
	 * @return PageInfo<ProcessDefinition>
	 * @throws
	 */
	public JqGridPageView<ProcessDefinition> findFlowByPage(Map<String, Object> params){
		JqGridPageView<ProcessDefinition> gridView=new JqGridPageView<ProcessDefinition>();
		int firstResult = 1;
		int maxResults = 10;
		String name=null;
		if(params.get("page")!=null){
			firstResult=Integer.parseInt((String)params.get("page"));
		}
		if(params.get("rows")!=null){
			maxResults = (Integer)params.get("rows");
		}
		if(params.get("queryname")!=null){
			name = (String)params.get("queryname");
		}
		ProcessDefinitionQuery processDefinitionQuery=null;
		//    String modelCategory=(String)params.get("modelCategory");
		if(name==null||"".equals(name)){
		 processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
				.latestVersion().active().orderByProcessDefinitionKey().asc();}
			else{
			processDefinitionQuery = repositoryService.createProcessDefinitionQuery().processDefinitionNameLike(name)
					.latestVersion().active().orderByProcessDefinitionKey().asc();
		}
		long count=processDefinitionQuery.count();
		List<org.activiti.engine.repository.ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage((firstResult - 1)*maxResults, maxResults);
		List<ProcessDefinition> dataList=new ArrayList<ProcessDefinition>();
		ProcessDefinition processDefinition = null;
		for (org.activiti.engine.repository.ProcessDefinition pd : processDefinitionList) {
			processDefinition = new ProcessDefinition();
			processDefinition.setId(pd.getId());
			processDefinition.setName(pd.getName());
			processDefinition.setKey(pd.getKey());
			processDefinition.setVersion(pd.getVersion() + "");
			processDefinition.setResourceName(pd.getResourceName());
			processDefinition.setDiagramResourceName(pd
					.getDiagramResourceName());
			processDefinition.setDeploymentId(pd.getDeploymentId());
			dataList.add(processDefinition);
		}
		gridView.setCurrentPage((firstResult - 1) * maxResults);
		gridView.setMaxResults(maxResults);
		gridView.setRecords(count);
		gridView.setRows(dataList);
		return gridView;
	}
	/**
	 *
	 * @Title delteProcessDefinitionByKey
	 * @Description (级联删除流程定义)
	 * @author 颜金星
	 * @create 2017年5月11日-下午3:28:24
	 * @Param
	 * @return void
	 * @throws
	 */
	public void delteProcessDefinitionByKey(Map<String, Object> params){
		// 流程定义的Key  
		String processDefinitionKey = params.get("key")+"";
		// 先使用流程定义的key查询流程定义，查询出所有的版本
		List<org.activiti.engine.repository.ProcessDefinition> list = processEngine.getRepositoryService()
				.createProcessDefinitionQuery()
				.processDefinitionKey(processDefinitionKey)// 使用流程定义的key查询
				.list();
		// 遍历，获取每个流程定义的部署ID
		if (list != null && list.size() > 0) {
			for (org.activiti.engine.repository.ProcessDefinition pd : list) {
				// 获取部署ID
				String deploymentId = pd.getDeploymentId();
				//      /*
				//       * 不带级联的删除， 只能删除没有启动的流程，如果流程启动，就会抛出异常
				//       */
				//       processEngine.getRepositoryService().deleteDeployment(deploymentId);

				/**
				 * 级联删除 不管流程是否启动，都可以删除
				 */
				processEngine.getRepositoryService().deleteDeployment(
						deploymentId, true);

			}

		}
	}
	/**
	 *
	 * @Title startProcessInstance
	 * @Description (启动流程实例)
	 * @author 颜金星
	 * @create 2017年5月11日-下午4:00:29
	 * @Param @param params
	 * @Param @return
	 * @return ProcessInstance
	 * @throws
	 */
	public String startProcessInstance(Map<String, Object> params){
		// 获取流程XML上的表单KEY
		//test_audit:2:20008
		String procDefId=(String)params.get("procDefId");
		String taskDefKey=(String)params.get("taskDefKey");
		String formKey = "";
		if (StringUtils.isNotBlank(procDefId)){

			try {
				formKey = formService.getTaskFormKey(procDefId, taskDefKey);
			} catch (Exception e) {
				formKey = "";
			}
			if (StringUtils.isBlank(formKey)){
				formKey = formService.getStartFormKey(procDefId);
			}
			if (StringUtils.isBlank(formKey)){
				formKey = "/404";
			}
		}
//    	 String processDefinitionKey = params.get("key")+"";    
//         ProcessInstance pi = processEngine.getRuntimeService()// 与正在执行的流程实例和执行对象相关的Service  
//                 .startProcessInstanceByKey(processDefinitionKey);// 使用流程定义的key启动流程实例，key对应bpmn文件中id的属性值，使用key值启动，默认是按照最新版本的流程定义启动  
//         System.out.println("流程实例成功");
//         System.out.println("流程实例ID:" + pi.getId());// 流程实例ID 101  
//         System.out.println("流程定义ID:" + pi.getProcessDefinitionId());
		return formKey;
	}
	/**
	 *
	 * @Title startProcessInstanceByForm
	 * @Description (启动动态表单)
	 * @author 颜金星
	 * @create 2017年5月12日-下午4:24:30
	 * @Param @param params
	 * @Param @return
	 * @return Map<String,Object>
	 * @throws
	 */
	public Map<String, Object> findProcessForm(Map<String, Object> params){
		String processDefinitionId=(String)params.get("processDefinitionId");
		Map<String, Object> result = new HashMap<String, Object>();
		StartFormDataImpl startFormData = (StartFormDataImpl) formService.getStartFormData(processDefinitionId);
		startFormData.setProcessDefinition(null);
         /*
         * 读取enum类型数据，用于下拉框
         */
		List<FormProperty> formProperties = startFormData.getFormProperties();
		for (FormProperty formProperty : formProperties) {
			Map<String, String> values = (Map<String, String>) formProperty.getType().getInformation("values");
			if (values != null) {
				for (Entry<String, String> enumEntry : values.entrySet()) {
					//    logger.debug("enum, key: {}, value: {}", enumEntry.getKey(), enumEntry.getValue());
				}
				result.put("enum_" + formProperty.getId(), values);
			}
		}
		result.put("form", startFormData);
		return result;
	}
	/**
	 *
	 * @Title startProcessByForm
	 * @Description (保存表单启动流程)
	 * @author 颜金星
	 * @create 2017年5月12日-下午5:15:06
	 * @Param @param params
	 * @Param @param request
	 * @return void
	 * @throws
	 */
	public void startProcessByForm(Map<String, Object> params,HttpServletRequest request){
		SysUserEntity userEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
		String userId=userEntity.getUserId()+"";
		String processDefinitionId=(String)params.get("processDefinitionId");
		Map<String, String> formProperties = new HashMap<String, String>();
		// 从request中读取参数然后转换
		Map<String, String[]> parameterMap = request.getParameterMap();
		Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
		for (Entry<String, String[]> entry : entrySet) {
			String key = entry.getKey();
			formProperties.put(key,request.getParameter(key) );
		}
		//  logger.debug("start form parameters: {}", formProperties);
		ProcessInstance processInstance = null;
		try {
			identityService.setAuthenticatedUserId(userId);
			processInstance = formService.submitStartFormData(processDefinitionId, formProperties);
			//logger.debug("start a processinstance: {}", processInstance);
		} finally {
			identityService.setAuthenticatedUserId(null);
		}
	}
	/**
	 *
	 * @Title getWorkFlowRunning
	 * @Description (查询运行中的流程实例)
	 * @author 颜金星
	 * @create 2017年5月15日-下午3:01:27
	 * @Param @param params
	 * @Param @return
	 * @return PageInfo<ProcessInstance>
	 * @throws
	 */
	public JqGridPageView<com.casic.modules.activiti.entity.ProcessInstance> getWorkFlowRunning(Map<String, Object> params){
		JqGridPageView<com.casic.modules.activiti.entity.ProcessInstance> gridView=new JqGridPageView<com.casic.modules.activiti.entity.ProcessInstance>();
		int firstResult = 1;
		int maxResults = 10;
		String name=null;
		if(params.get("page")!=null){
			firstResult=Integer.parseInt((String)params.get("page"));
		}
		if(params.get("rows")!=null){
			maxResults = (Integer)params.get("rows");
		}
		if(params.get("queryname")!=null){
			name = (String)params.get("queryname");
		}
		Session session = SecurityUtils.getSubject().getSession();
		SysUserEntity userEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
		String userId=userEntity.getUserId()+"";
		ProcessInstanceQuery dynamicQuery=null;
		if(name!=null){
			dynamicQuery = runtimeService.createProcessInstanceQuery().processDefinitionName(name).involvedUser(userId).orderByProcessInstanceId().desc().active();
		}
		else{
			dynamicQuery = runtimeService.createProcessInstanceQuery().involvedUser(userId).orderByProcessInstanceId().desc().active();

		}
		// dynamicQuery = runtimeService.createProcessInstanceQuery().processDefinitionName().involvedUser(userId).orderByProcessInstanceId().desc().active();
		List<ProcessInstance> list = dynamicQuery.listPage((firstResult - 1)*maxResults, maxResults);
		com.casic.modules.activiti.entity.ProcessInstance processInstance=null;
		ProcessDefinition processDefinitionData=null;
		List<com.casic.modules.activiti.entity.ProcessInstance> dataList=new ArrayList<com.casic.modules.activiti.entity.ProcessInstance>();
		for(int i=0;i<list.size();i++){
			ProcessInstance entity=list.get(i);
			processInstance=new com.casic.modules.activiti.entity.ProcessInstance();
			processDefinitionData=new ProcessDefinition();
			org.activiti.engine.repository.ProcessDefinition processDefinition= WorkFlowUtils.getProcessDefinitionByProcDefId(entity.getProcessDefinitionId(), repositoryService);
			processDefinitionData.setId(processDefinition.getId());
			processDefinitionData.setName(processDefinition.getName());
			processDefinitionData.setKey(processDefinition.getKey());
			processDefinitionData.setVersion(processDefinition.getVersion()+"");
			processDefinitionData.setResourceName(processDefinition.getResourceName());
			processDefinitionData.setDiagramResourceName(processDefinition.getDiagramResourceName());
			processDefinitionData.setDeploymentId(processDefinition.getDeploymentId());
			processInstance.setProcessDefinition(processDefinitionData);
			processInstance.setId(entity.getId());
			processInstance.setActivityId(entity.getActivityId());
//    		 ActivityImpl activityImpl=WorkFlowUtils.getActivityName(entity.getProcessDefinitionId(), entity.getActivityId());
//    		 processInstance.setActivityName(ObjectUtils.toString(activityImpl.getProperty("name")));
			processInstance.setProcessDefinitionId(entity.getProcessDefinitionId());
			processInstance.setSuspended(entity.isSuspended()+"");
			dataList.add(processInstance);
		}
		long count=dynamicQuery.count();
		gridView.setCurrentPage((firstResult - 1) * maxResults);
		gridView.setMaxResults(maxResults);
		gridView.setRecords(count);
		gridView.setRows(dataList);
		return gridView;
	}
	/**
	 *
	 * @Title finished
	 * @Description (查询以结束流程)
	 * @author 颜金星
	 * @create 2017年5月15日-下午4:38:48
	 * @Param @param params
	 * @Param @return
	 * @return PageInfo<HistoricProcessInstance>
	 * @throws
	 */
	public JqGridPageView<HistoricProcessInstance> finished(Map<String, Object> params){
		JqGridPageView<HistoricProcessInstance> gridView=new JqGridPageView<HistoricProcessInstance>();
		int firstResult = 1;
		int maxResults = 10;
		String name=null;
		if(params.get("page")!=null){
			firstResult=Integer.parseInt((String)params.get("page"));
		}
		if(params.get("rows")!=null){
			maxResults = (Integer)params.get("rows");
		}
		if(params.get("queryname")!=null){
			name = (String)params.get("queryname");
		}
		Session session = SecurityUtils.getSubject().getSession();
		SysUserEntity userEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
		String userId=userEntity.getUserId()+"";
		HistoricProcessInstanceQuery dynamicQuery=null;
		if(name!=null){

			dynamicQuery = historyService.createHistoricProcessInstanceQuery().processDefinitionName(name).involvedUser(userId)
					.finished().orderByProcessInstanceEndTime().desc();
		}
		else{
			dynamicQuery = historyService.createHistoricProcessInstanceQuery().involvedUser(userId)
					.finished().orderByProcessInstanceEndTime().desc();
		}

		List<HistoricProcessInstance> list = dynamicQuery.listPage((firstResult - 1)*maxResults, maxResults);
		long count=dynamicQuery.count();
		gridView.setCurrentPage((firstResult - 1) * maxResults);
		gridView.setMaxResults(maxResults);
		gridView.setRecords(count);
		gridView.setRows(list);
		return gridView;
	}
	/**
	 *
	 * @Title loadByDeployment
	 * @Description (获取流程定义的图片资源和XML资源)
	 * @author 颜金星
	 * @create 2017年6月8日-下午4:29:26
	 * @Param @param params
	 * @Param @param response
	 * @Param @throws IOException
	 * @return void
	 * @throws
	 */
	public void loadByDeployment(Map<String, Object> params,HttpServletResponse response) throws IOException{
		String processDefinitionId=(String)params.get("processDefinitionId");
		String resourceType=(String)params.get("resourceType");
		org.activiti.engine.repository.ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
		String resourceName = "";
		if (resourceType.equals("image")) {
			resourceName = processDefinition.getDiagramResourceName();
		} else if (resourceType.equals("xml")) {
			resourceName = processDefinition.getResourceName();
		}
		InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
		byte[] b = new byte[1024];
		int len = -1;
		while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
			response.getOutputStream().write(b, 0, len);
		}
	}


	/**
	 *
	 * @Title instance
	 * @Description (流程实例跟踪图片)
	 * @author 颜金星
	 * @create 2017年5月16日-上午11:24:46
	 * @Param @param params
	 * @Param @param response
	 * @Param @throws IOException
	 * @return void
	 * @throws
	 */
	public void instance(Map<String, Object> params,HttpServletResponse response) throws IOException{
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		String executionId=(String)params.get("executionId");
		ProcessInstance processInstance = runtimeService
				.createProcessInstanceQuery().processInstanceId(executionId)
				.singleResult();
		ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(processInstance
						.getProcessDefinitionId());
		BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance
				.getProcessDefinitionId());
		//获取流程历史节点
		List activityInstances = historyService
				.createHistoricActivityInstanceQuery()
				.processInstanceId(executionId)
				.orderByHistoricActivityInstanceStartTime().asc()
				.list();
		List flowIds = new ArrayList();
		//当前流程执行节点
		List<String> activeActivityIds = runtimeService
				.getActiveActivityIds(executionId);
		flowIds = getHighLightedFlows(processDefinition,
				activityInstances);//
		// 使用spring注入引擎请使用下面的这行代码
		processEngineConfiguration = processEngine
				.getProcessEngineConfiguration();
		Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);
		ProcessDiagramGenerator diagramGenerator = processEngineConfiguration
				.getProcessDiagramGenerator();
		//设置图片字体，防止乱码
		InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel,
				"png", activeActivityIds, flowIds, "宋体", "宋体",
				null, null, 1.0);
		// 输出资源内容到相应对象
		byte[] b = new byte[1024];
		int len;
		while ((len = imageStream.read(b, 0, 1024)) != -1) {
			response.getOutputStream().write(b, 0, len);
		}
	}
	/**
	 *
	 * @Title getHighLightedFlows
	 * @Description (流程走过的线高亮显示)
	 * @author 颜金星
	 * @create 2017年5月16日-上午11:42:04
	 * @Param @param processDefinitionEntity
	 * @Param @param historicActivityInstances
	 * @Param @return
	 * @return List
	 * @throws
	 */
	public List getHighLightedFlows(
			ProcessDefinitionEntity processDefinitionEntity,
			List historicActivityInstances) {

		List highFlows = new ArrayList();// 用 以保存高亮的线flowId
		for (int i = 0; i < historicActivityInstances.size() - 1; i++) {// 对历史流程节点进行遍历
			ActivityImpl activityImpl = processDefinitionEntity
					.findActivity(((HistoricActivityInstance) historicActivityInstances
							.get(i)).getActivityId());// 得到节点定义的详细信息

			List sameStartTimeNodes = new ArrayList(); // 用以保存后需开始时间相同的节点
			ActivityImpl sameActivityImpl1 = processDefinitionEntity
					.findActivity(((HistoricActivityInstance) historicActivityInstances
							.get(i + 1)).getActivityId()); // 将后面第一个节点放在时间相同节点的集合里
			sameStartTimeNodes.add(sameActivityImpl1);
			for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
				HistoricActivityInstance activityImpl1 = (HistoricActivityInstance) historicActivityInstances
						.get(j); // 后续第一个节点
				HistoricActivityInstance activityImpl2 = (HistoricActivityInstance) historicActivityInstances
						.get(j + 1); // 后续第二个节点
				if (activityImpl1.getStartTime().equals(
						activityImpl2.getStartTime())) { // 如果第一个节点和第二个节点开始时间相同保存
					ActivityImpl sameActivityImpl2 = processDefinitionEntity
							.findActivity(activityImpl2.getActivityId());
					sameStartTimeNodes.add(sameActivityImpl2);
				} else {
					break;
				}
			}
			List<PvmTransition> pvmTransitions = activityImpl
					.getOutgoingTransitions();// 取出节点的所有出去的线
			for (PvmTransition pvmTransition : pvmTransitions) { // 对所有的线进行遍历
				ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition
						.getDestination();// 如果取出的线的目标节点存在时间相同的节点里，保存该线的id，进行高亮显示
				if (sameStartTimeNodes.contains(pvmActivityImpl)) {
					highFlows.add(pvmTransition.getId());
				}
			}

		}
		return highFlows;
	}

	public JqGridPageView<HistoricActivity> histoicFlow(Map<String, Object> params){
		String procInsId=(String)params.get("procInsId");
		JqGridPageView<HistoricActivity> gridView=new JqGridPageView<HistoricActivity>();
		int firstResult = 1;
		int maxResults = 10;
		if(params.get("page")!=null){
			firstResult=Integer.parseInt((String)params.get("page"));
		}
		if(params.get("rows")!=null){
			maxResults =(Integer)params.get("rows");
		}
		List<HistoricActivity> listData=new ArrayList<HistoricActivity>();
		HistoricActivityInstanceQuery historicActivityInstanceQuery=historyService.createHistoricActivityInstanceQuery();
		List<HistoricActivityInstance> list = historicActivityInstanceQuery.processInstanceId(procInsId)
				.orderByHistoricActivityInstanceStartTime().asc().orderByHistoricActivityInstanceEndTime().asc().listPage(firstResult-1, maxResults);
		HistoricActivity historicActivity=null;
		int count=0;
		for(int i=0;i<list.size();i++){
			historicActivity=new HistoricActivity();
			HistoricActivityInstance historicActivityInstance=list.get(i);
			System.out.println(historicActivityInstance.getTenantId());
			//去掉网管节点
			if("exclusiveGateway".equals(historicActivityInstance.getActivityType())){
				continue;
			}
			historicActivity.setProcessInstanceId(historicActivityInstance.getProcessInstanceId());
			historicActivity.setActivityId(historicActivityInstance.getActivityId());
			historicActivity.setActivityName(historicActivityInstance.getActivityName());
			historicActivity.setActivityType(historicActivityInstance.getActivityType());
			historicActivity.setExecutionId(historicActivityInstance.getExecutionId());
			historicActivity.setStartTime(historicActivityInstance.getStartTime());
			historicActivity.setEndTime(historicActivityInstance.getEndTime());
			historicActivity.setTaskId(historicActivityInstance.getTaskId());
			String assignee=historicActivityInstance.getAssignee();
			if(assignee!=null){
				SysUserEntity sysUser= sysUserService.queryObject(assignee);
				if(sysUser!=null) {
					historicActivity.setAssignee(sysUser.getUsername());
				}
			}
			//判断开始节点,查询流程发起人名称
			if ("startEvent".equals(historicActivityInstance.getActivityType())){
				List<HistoricProcessInstance> il = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).orderByProcessInstanceStartTime().asc().list();
				if(il.size()>0){
					String userId=il.get(0).getStartUserId();
					SysUserEntity sysUser= sysUserService.queryObject(userId);
					historicActivity.setAssignee(sysUser.getUsername());
				}
			}
			//获取审核人的审核意见
			if(historicActivity.getTaskId()!=null){
				List<Comment> comments=taskService.getTaskComments(historicActivity.getTaskId());
				if(comments.size()>0){
					historicActivity.setFullMessage(comments.get(0).getFullMessage());
				}
			}
			if(historicActivityInstance.getEndTime()!=null){
				historicActivity.setDuration((historicActivity.getEndTime().getTime()-historicActivity.getStartTime().getTime())/1000);
			}
			listData.add(historicActivity);
			count++;
		}
		gridView.setCurrentPage((firstResult - 1) * maxResults);
		gridView.setMaxResults(maxResults);
		gridView.setRecords(count);
		gridView.setRows(listData);
		return gridView;
	}
}
